using System;
using System.Linq.Expressions;
using FluentNHibernate.Mapping;
using Caramel.Entities;

namespace Caramel.FluentNHibernate.Mapping
{
	public static class ClassMapExtensions
	{
		public static void MapImmutable<T>(this ClassMap<T> map) where T : IImmutable
		{
			map.Map(e => e.Created).
				Not.
				Update();

			map.Map(e => e.CreatedBy).
				Not.
				Update();
		}

		public static void MapMutable<T>(this ClassMap<T> map) where T : IMutable
		{
			map.Map(e => e.Updated).
				Not.
				Insert();

			map.Map(e => e.UpdatedBy).
				Not.
				Insert();

			map.Version(e => e.Version).
				Not.
				Nullable();
		}

		public static void MapPerson<T>(this ClassMap<T> map) where T : IPerson
		{
			map.Map(e => e.Prefix);

			map.Map(e => e.FirstName);

			map.Map(e => e.MiddleName);

			map.Map(e => e.LastName);

			map.Map(e => e.Suffix);
		}

		public static void MapNamedEntity<T>(this ClassMap<T> map) where T : INamedEntity
		{
			map.Map(e => e.Name).
				Not.
				Nullable().
				UniqueKey("Name");

			map.Map(e => e.IsActive).
				Not.
				Nullable();
		}

		public static void MapSequencedEntity<T>(this ClassMap<T> map) where T : ISequencedEntity
		{
			map.Map(e => e.Sequence).
				Not.
				Nullable().
				Default("0");
		}

		public static void MapAddress<T>(this ClassMap<T> map, Expression<Func<T, Address<string>>> expression)
		{
			map.Component<Address<string>>(
				expression,
				component =>
				{
					component.
						Map(address => address.PrimaryAddress);
					component.
						Map(address => address.SecondaryAddress);
					component.
						Map(address => address.City);
					component.
						Map(address => address.Region);
					component.
						Map(address => address.PostalCode);
				}
			);
		}
	}
}
